Skip to content

feat: RPC improvements#600

Merged
zeljkoX merged 10 commits into
mainfrom
rpc-impr
Jan 12, 2026
Merged

feat: RPC improvements#600
zeljkoX merged 10 commits into
mainfrom
rpc-impr

Conversation

@zeljkoX

@zeljkoX zeljkoX commented Dec 30, 2025

Copy link
Copy Markdown
Collaborator

Summary

This PR will:

  • introduce networks route with get, list and partial patch support
  • improve rpc errors response(sanitize)
  • extend internal rpc model to support weights
  • improve logic for failing rpc providers
  • fix jupiter service tests
  • mask custom_rpc_urls url response(sensitive info)

SDK PR: OpenZeppelin/openzeppelin-relayer-sdk#242

Testing Process

Checklist

  • Add a reference to related issues in the PR description.
  • Add unit tests if applicable.

Note

If you are using Relayer in your stack, consider adding your team or organization to our list of Relayer Users in the Wild!

Summary by CodeRabbit

  • New Features

    • Added Networks API endpoints for listing, retrieving, and updating network configurations.
    • Introduced provider health management with automatic failure tracking and recovery configuration.
  • Documentation

    • Added documentation for provider health management environment variables and behavior.
  • Bug Fixes

    • Improved error handling to sanitize sensitive information in error responses.

✏️ Tip: You can customize this high-level summary in your review settings.

@zeljkoX
zeljkoX requested a review from a team as a code owner December 30, 2025 22:31
@coderabbitai

coderabbitai Bot commented Dec 30, 2025

Copy link
Copy Markdown

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This pull request introduces provider health management, adds a Networks API for RPC URL configuration, refactors RPC URL representation from strings to a structured RpcConfig type across the codebase, centralizes provider creation through ProviderConfig, and implements a shared health tracking store for monitoring provider failures and automatic pausing.

Changes

Cohort / File(s) Summary
Documentation Updates
docs/configuration/index.mdx
Adds three provider health management environment variables (PROVIDER_FAILURE_THRESHOLD, PROVIDER_PAUSE_DURATION_SECS, PROVIDER_FAILURE_EXPIRATION_SECS) with descriptions and defaults to configuration docs.
OpenAPI Specifications
openapi.json
Introduces /api/v1/networks endpoints (GET, GET/{id}, PATCH/{id}) with NetworkResponse, UpdateNetworkRequest, RpcUrlEntry schemas, and RpcConfig updates marking weight as required.
API Routes & Controllers
src/api/routes/network.rs, src/api/routes/mod.rs, src/api/controllers/network.rs, src/api/routes/docs/network_docs.rs, src/api/routes/docs/mod.rs
Implements new network management HTTP handlers (list, get, update) with pagination support, request validation, and OpenAPI documentation via utoipa.
Configuration Management
src/config/server_config.rs, src/constants/relayer.rs
Adds three public fields to ServerConfig for provider health thresholds and durations with environment variable support and default constants.
Network Configuration
src/config/config_file/network/common.rs, src/config/config_file/network/*.rs, src/config/config_file/mod.rs
Refactors rpc_urls from Vec<String> to Vec<RpcConfig> with custom deserializer supporting both simple (string array) and extended (RpcConfig array) formats; adds merge helper function.
RpcConfig Core Type
src/models/relayer/rpc_config.rs
Enhances RpcConfig with Hash/Default derives, ToSchema attribute, manual Serialize/Deserialize implementations, validation methods (validate_url_scheme, validate_list), and constructors (new, with_weight).
Networks Model & Repository
src/models/network/request.rs, src/models/network/response.rs, src/models/network/mod.rs, src/models/network/evm/network.rs, src/models/network/solana/network.rs, src/models/network/stellar/network.rs
Introduces UpdateNetworkRequest with custom RPC URL deserialization; implements NetworkResponse for API responses; updates all network models to use Vec for rpc_urls field and public_rpc_urls method.
Provider Health Tracking
src/services/provider/rpc_health_store.rs
Implements new RpcHealthStore singleton for thread-safe, shared tracking of RPC provider failures, pause states, and expiration windows with methods for marking failures, checking pause status, and resetting state.
Provider Infrastructure Refactoring
src/services/provider/mod.rs, src/services/provider/evm/mod.rs, src/services/provider/solana/mod.rs, src/services/provider/stellar/mod.rs, src/services/provider/retry.rs, src/services/provider/rpc_selector.rs
Centralizes provider creation through new ProviderConfig struct; updates NetworkConfiguration trait to return Vec<RpcConfig> from public_rpc_urls and accept ProviderConfig in new_provider; refactors RpcSelector to use shared RpcHealthStore for health management with new constructor parameters and get_configs/get_next_url methods; introduces excluded_urls tracking in retry logic.
Error Handling Utilities
src/utils/error_sanitization.rs, src/utils/mod.rs, src/domain/relayer/evm/rpc_utils.rs
Adds new error_sanitization module with map_provider_error and sanitize_error_description functions to translate provider errors to user-friendly messages; re-exports from rpc_utils for backward compatibility.
RPC URL Type Migration
src/domain/relayer/evm/evm_relayer.rs, src/domain/relayer/solana/solana_relayer.rs, src/domain/relayer/stellar/stellar_relayer.rs, src/domain/relayer/stellar/gas_abstraction.rs, src/domain/relayer/stellar/token_swap.rs, src/domain/transaction/evm/*, src/services/gas/*
Updates all EVM, Solana, and Stellar relayer implementations to use RpcConfig for rpc_urls; integrates error sanitization in RPC error handling paths; updates all test fixtures and mock network configurations.
Jupiter Swap Models
src/services/jupiter/mod.rs, src/domain/relayer/solana/dex/jupiter_swap.rs, src/domain/relayer/solana/dex/jupiter_ultra.rs, src/domain/relayer/solana/rpc/methods/*.rs
Changes fee_amount and fee_mint fields in SwapInfo from String to Option<String> with serde(default) attributes across all Jupiter-related modules and tests.
Mock Utilities & Test Helpers
src/utils/mocks.rs, src/domain/transaction/stellar/test_helpers.rs, src/repositories/relayer/mod.rs, src/models/relayer/mod.rs
Updates mock network configurations to use RpcConfig; changes TestMocks relayer_repo from MockRepository<RelayerRepoModel, String> to MockRelayerRepository; adds mockall-based mocks for RelayerRepository trait.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API as Network API<br/>(Controller)
    participant Repo as Network<br/>Repository
    participant Store as RpcHealthStore<br/>(Singleton)
    participant Provider as RPC Provider

    rect rgb(240, 248, 255)
    Note over Client,Provider: Getting Network with Health Status
    Client->>API: GET /api/v1/networks/{id}
    API->>Repo: fetch_network(id)
    Repo-->>API: NetworkRepoModel
    API->>API: Convert to NetworkResponse
    Note over API: rpc_urls include<br/>weight & health data
    API-->>Client: 200 OK NetworkResponse
    end

    rect rgb(240, 248, 255)
    Note over Client,Provider: Updating Network RPC URLs
    Client->>API: PATCH /api/v1/networks/{id}<br/>UpdateNetworkRequest
    API->>API: Validate non-empty rpc_urls
    API->>API: RpcConfig::validate_list()
    API->>Repo: fetch_network(id)
    Repo-->>API: NetworkRepoModel
    API->>API: Merge RPC configs<br/>(child overrides parent)
    API->>Repo: save(updated_network)
    Repo-->>API: Success
    API-->>Client: 200 OK NetworkResponse
    end

    rect rgb(240, 248, 255)
    Note over Client,Provider: Provider Failure Tracking
    Provider->>Store: mark_failed(url, threshold=3<br/>pause_duration=60s<br/>failure_expiration=60s)
    Store->>Store: Append failure_timestamp
    Store->>Store: Prune stale timestamps
    alt Failures >= Threshold
        Store->>Store: Set paused_until = now + 60s
        Store->>Store: Log "Provider paused"
    end
    Store-->>Provider: Metadata updated
    end

    rect rgb(240, 248, 255)
    Note over Provider,Store: Provider Recovery Check
    Provider->>Store: is_paused(url, threshold=3<br/>failure_expiration=60s)
    alt Pause expired
        Store->>Store: Clear paused_until
        Store->>Store: Check if stale failures remain
    else Still paused
        Store-->>Provider: true (paused)
    end
    Store-->>Provider: false (available)
    end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120+ minutes

This review involves substantial, multi-system changes with high complexity:

  • New concurrent health tracking system with shared singleton state management (RpcHealthStore) requiring careful validation of thread safety and consistency
  • Wide-ranging RPC URL refactor touching 50+ files, changing core type signatures across providers (EVM, Solana, Stellar) and configuration layers
  • Provider infrastructure rework centralizing creation through ProviderConfig with complex parameter flows across three provider implementations
  • New API endpoints with request validation, OpenAPI documentation, and repository integration
  • Error handling changes affecting provider error paths across multiple domains
  • Heterogeneous changes across configuration, models, services, and domain layers requiring separate reasoning for each system
  • Test fixture updates across many files with substantial but mostly repetitive RpcConfig wrapping changes

Possibly related PRs

Suggested labels

cla: allowlist, feature: networks-api, feature: provider-health, refactor: rpc-config

Suggested reviewers

  • shahnami
  • dylankilkenny
  • tirumerla

Poem

🐰 A health-monitored hop through networks new,
RPC configs tracked in stores so true,
When providers stumble, they pause and wait,
Then recover strong to handle their fate! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'feat: RPC improvements' is vague and generic, using non-descriptive terms that don't clearly convey the specific changes (networks API, error sanitization, health management). Provide a more specific title that highlights the main changes, e.g., 'feat: Add networks API with RPC health management and error sanitization'.
✅ Passed checks (2 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed The PR description covers the main objectives and includes relevant checklist items, though the testing process details are missing.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch rpc-impr

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Dec 30, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.64356% with 132 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.36%. Comparing base (f350048) to head (937ddc2).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/services/provider/rpc_health_store.rs 90.85% 47 Missing ⚠️
src/api/routes/network.rs 20.83% 19 Missing ⚠️
src/services/provider/retry.rs 90.95% 19 Missing ⚠️
src/services/provider/rpc_selector.rs 98.26% 10 Missing ⚠️
src/models/relayer/rpc_config.rs 97.42% 7 Missing ⚠️
src/services/provider/evm/mod.rs 81.25% 6 Missing ⚠️
src/services/provider/solana/mod.rs 91.66% 6 Missing ⚠️
src/services/provider/stellar/mod.rs 88.00% 6 Missing ⚠️
...er/solana/rpc/methods/sign_and_send_transaction.rs 66.66% 4 Missing ⚠️
src/api/controllers/network.rs 98.79% 2 Missing ⚠️
... and 5 more
Additional details and impacted files
Flag Coverage Δ
ai 0.32% <0.09%> (-0.01%) ⬇️
dev 92.35% <95.64%> (+0.05%) ⬆️
properties 0.02% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

@@            Coverage Diff             @@
##             main     #600      +/-   ##
==========================================
+ Coverage   92.30%   92.36%   +0.05%     
==========================================
  Files         250      257       +7     
  Lines       90865    93113    +2248     
==========================================
+ Hits        83875    86005    +2130     
- Misses       6990     7108     +118     
Files with missing lines Coverage Δ
src/api/controllers/relayer.rs 52.85% <100.00%> (+0.15%) ⬆️
src/api/routes/relayer.rs 50.18% <100.00%> (ø)
src/config/config_file/mod.rs 97.05% <100.00%> (+0.05%) ⬆️
src/config/config_file/network/common.rs 99.68% <100.00%> (+0.12%) ⬆️
src/config/config_file/network/evm.rs 100.00% <100.00%> (ø)
src/config/config_file/network/inheritance.rs 99.78% <100.00%> (+<0.01%) ⬆️
src/config/config_file/network/mod.rs 98.41% <100.00%> (+0.01%) ⬆️
src/config/config_file/network/test_utils.rs 100.00% <100.00%> (ø)
src/config/server_config.rs 97.06% <100.00%> (+0.12%) ⬆️
src/domain/relayer/evm/evm_relayer.rs 98.83% <100.00%> (+<0.01%) ⬆️
... and 52 more

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread src/api/controllers/network.rs Fixed
Comment thread src/api/controllers/network.rs Fixed
Comment thread src/api/controllers/network.rs Fixed
Comment thread src/api/controllers/network.rs Fixed
Comment thread src/models/network/request.rs Fixed
Comment thread src/models/network/request.rs Fixed
Comment thread src/utils/error_sanitization.rs Fixed
Comment thread src/utils/error_sanitization.rs Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
src/domain/relayer/solana/solana_relayer.rs (1)

762-804: Fix use-after-move of request in rpc method

The destructuring at lines 766-770 moves request, after which line 800 attempts to access request.jsonrpc, causing a compile error. Capture jsonrpc into a local variable instead of discarding it, then reuse that variable.

Proposed fix
         let JsonRpcRequest {
-            jsonrpc: _,
+            jsonrpc,
             id,
             params,
         } = request;

Then at line 800:

                 let response = self
                     .rpc_handler
                     .handle_request(JsonRpcRequest {
-                        jsonrpc: request.jsonrpc,
+                        jsonrpc,
                         params: NetworkRpcRequest::Solana(solana_request),
                         id: id.clone(),
                     })
src/services/provider/evm/mod.rs (1)

155-191: Fix infinite recursion in get_configs() implementations across all provider traits

The trait implementations for EvmProviderTrait, StellarProviderTrait, and SolanaProviderTrait all have the same critical bug: their get_configs() methods call self.get_configs(), which resolves to the trait method itself rather than the inherent method, causing infinite recursion at runtime.

Each provider has a correct inherent method that delegates to the selector (e.g., self.selector.get_configs()), but the trait implementations bypass this by calling the trait method recursively.

Call the inherent method explicitly to fix this:

Proposed fix
 #[async_trait]
 impl EvmProviderTrait for EvmProvider {
     fn get_configs(&self) -> Vec<RpcConfig> {
-        self.get_configs()
+        EvmProvider::get_configs(self)
     }
 }

Apply the same pattern to StellarProviderTrait and SolanaProviderTrait.

openapi.json (1)

7104-7142: Align RpcConfig/RpcUrlEntry docs with enforced weight bounds.

The RpcConfig schema correctly documents weight as 0–100 with maximum: 100 and a default of 100, matching the Rust-side intent.

Given that, please double‑check all usages/examples that mention weights via RpcUrlEntry to ensure they stay within this range (see UpdateNetworkRequest below where an example uses 200). Keeping examples inside the documented bounds avoids confusing clients and mismatches with server-side validation.

src/services/provider/solana/mod.rs (1)

353-359: Avoid possible recursion in SolanaProviderTrait::get_configs

You’ve added an inherent method:

impl SolanaProvider {
    pub fn get_configs(&self) -> Vec<RpcConfig> {
        self.selector.get_configs()
    }
}

and the trait impl currently does:

impl SolanaProviderTrait for SolanaProvider {
    fn get_configs(&self) -> Vec<RpcConfig> {
        self.get_configs()
    }
    // ...
}

Because both the trait method and the inherent method have the same name and signature, self.get_configs() here can resolve back to the trait method, causing infinite recursion.

To make the intent explicit and avoid any ambiguity, call the inherent method via fully qualified syntax:

Proposed fix
 #[async_trait]
 #[allow(dead_code)]
 impl SolanaProviderTrait for SolanaProvider {
-    fn get_configs(&self) -> Vec<RpcConfig> {
-        self.get_configs()
-    }
+    fn get_configs(&self) -> Vec<RpcConfig> {
+        SolanaProvider::get_configs(self)
+    }

Also applies to: 642-648

♻️ Duplicate comments (1)
src/domain/relayer/solana/rpc/methods/sign_transaction.rs (1)

560-577: Same SwapInfo option-field change as above

This block mirrors the earlier Jupiter mock change; the same reasoning and suggestions apply.

Also applies to: 570-573

🧹 Nitpick comments (36)
src/domain/transaction/evm/status.rs (1)

736-738: Tests now correctly use RpcConfig for rpc_urls

The test helpers and imports are correctly updated to construct rpc_urls as Vec<RpcConfig>, which matches the new network model and keeps status logic untouched. One minor nit: since RpcConfig is imported (Line 736), you can drop the crate::models:: qualifier in the few places that still use crate::models::RpcConfig::new(...) for consistency.

Also applies to: 803-805, 829-832, 1212-1214

src/models/transaction/repository.rs (1)

1701-1703: Test network configs aligned with RpcConfig

The EVM, Solana, and Stellar test NetworkConfigCommon fixtures now use rpc_urls: Vec<RpcConfig>, which is consistent with the new RPC model and keeps TransactionRepoModel::try_from behavior intact. If you touch this file again, you could import RpcConfig at the top and drop the repeated crate::models:: prefix in tests for slightly cleaner code.

Also applies to: 1785-1787, 1863-1865, 2125-2127

src/services/jupiter/mod.rs (1)

53-59: Making Jupiter fee fields optional is consistent and safely wired

Turning SwapInfo.fee_amount and fee_mint into Option<String> with #[serde(default)] is a good fit for handling routes where Jupiter omits these fields. The mock service and HTTP tests are correctly updated to set Some(...) values, so existing expectations still hold while allowing real responses to leave them out.

If you ever need to serialize SwapInfo back out (beyond tests), consider adding #[serde(skip_serializing_if = "Option::is_none")] on these fields to avoid emitting null keys, but that’s not required for current usage.

Also applies to: 410-419, 470-479, 684-686, 755-757

src/api/controllers/mod.rs (1)

13-18: Expose network controller and keep docs in sync

Re‑exporting the network controller from this module is the right hook for the new Networks API. As a small follow‑up, you might also add a * network – Network configuration endpoints entry to the controller list in the module docs to keep the documentation complete.

src/services/gas/fetchers/default.rs (1)

46-48: Tests correctly adapted to RpcConfig, consider importing it once

Using crate::models::RpcConfig::new(...) for rpc_urls matches the new type and is functionally fine. For readability you might add a single use crate::models::RpcConfig; at the top of the test module and use RpcConfig::new(...) everywhere instead of repeating the fully-qualified path.

Also applies to: 76-78, 105-107, 135-137, 165-167

src/domain/transaction/evm/utils.rs (1)

229-231: Unify RpcConfig imports in the test module

The switch of rpc_urls to RpcConfig is correct. You currently mix a fully-qualified path in create_standard_network with function-local use crate::models::RpcConfig; in the Arbitrum helpers. Consider a single use crate::models::RpcConfig; at the top of the test module and using RpcConfig::new(...) consistently.

Also applies to: 245-249, 262-266

src/domain/relayer/solana/rpc/methods/sign_transaction.rs (1)

327-345: SwapInfo fee fields updated correctly to Option<String>

Using Some("10".to_string()) / Some("…".to_string()) matches the new optional fee fields and keeps existing behavior for the “has fee” path. You may eventually want an additional test exercising the None case for fee_amount / fee_mint to ensure the validation and routing logic are robust when Jupiter omits these.

Also applies to: 337-340

src/repositories/network/network_redis.rs (1)

657-664: Tests updated to RpcConfig correctly; consider a shared import

The move from Vec<String> to Vec<RpcConfig> in NetworkConfigCommon.rpc_urls is correct and keeps these tests aligned with the model. To reduce repetition, you could add use crate::models::RpcConfig; at the top of the test module and use RpcConfig::new(...) instead of crate::models::RpcConfig::new(...) in both helpers.

Also applies to: 943-955

src/domain/transaction/evm/price_calculator.rs (1)

704-708: Consolidate RpcConfig imports in EVM price calculator tests

The mock networks’ rpc_urls now correctly use RpcConfig::new(...). Since multiple helpers/tests import RpcConfig locally, you can simplify by adding use crate::models::RpcConfig; once at the top of the tests module and dropping the per-function use statements.

Also applies to: 721-730, 2073-2077

src/config/config_file/network/test_utils.rs (1)

18-23: Helpers moved to RpcConfig correctly; reduce repeated local imports

All the helper constructors now build rpc_urls as Vec<RpcConfig>, which matches the updated config model and keeps the tests in sync. To declutter, you could add a single use crate::models::RpcConfig; at the top of this module and drop the per-function use lines, then keep using RpcConfig::new(...) in each helper. The JSON factory helpers that still emit URL strings are fine since they’re validating the file format, not the in-memory type.

Also applies to: 101-109, 120-128, 139-147, 160-168

src/domain/relayer/stellar/stellar_relayer.rs (1)

4-4: Sanitized Stellar RPC error handling looks solid; consider tightening test expectations

The switch to map_provider_error + sanitize_error_description with an internal tracing::error! log gives you centralized, non‑leaky RPC error responses while keeping full detail in logs. The wiring into create_error_response is correct and type‑safe.

You might optionally strengthen rpc_tests::test_rpc_provider_error to assert the mapped error code and sanitized description (e.g., that it no longer exposes the underlying ProviderError::Other message), so future changes to the sanitization layer are caught by tests rather than accidentally regressing to raw provider strings.

Also applies to: 571-590, 3067-3116

src/domain/relayer/solana/rpc/methods/transfer_transaction.rs (1)

540-543: SwapInfo fee fields correctly updated to Option<String> in tests

Using Some("...".to_string()) for fee_amount and fee_mint matches the new SwapInfo signature and keeps the Jupiter quote mocks in sync with the production type. If you don’t already have coverage elsewhere, consider adding at least one test path where these fields are None to exercise the optional case end‑to‑end.

Also applies to: 703-706

src/domain/relayer/solana/rpc/methods/sign_and_send_transaction.rs (1)

454-457: Tests aligned with optional SwapInfo fee metadata

All updated mocks now construct SwapInfo { fee_amount: Some(...), fee_mint: Some(...) }, which is consistent with the new optional fields and keeps sign‑and‑send flows compiling and semantically correct. As with the transfer tests, you may want a negative/None case somewhere in the suite if the runtime logic branches on missing fee metadata.

Also applies to: 630-633, 809-812

docs/configuration/index.mdx (1)

68-70: Provider health configuration docs are clear and consistent

The new PROVIDER_FAILURE_THRESHOLD, PROVIDER_PAUSE_DURATION_SECS, and PROVIDER_FAILURE_EXPIRATION_SECS entries are documented coherently in the table, sample .env, and the “Provider Health Management” section, and the behavior description (failure window, pausing, recovery, and fallback) matches the variable semantics. As a small polish, consider explicitly stating whether recovery on failure expiration can happen before PROVIDER_PAUSE_DURATION_SECS elapses, to mirror the exact implementation and avoid ambiguity.

Also applies to: 105-107, 308-323

src/config/config_file/network/collection.rs (1)

832-875: New mixed-type networks deserialization test looks good; tighten variant checks

The updated test_deserialize_networks_array nicely exercises array-based deserialization for both EVM and Solana, including chain_id, rpc_urls, average_blocktime_ms, and is_testnet. To make this test more robust against accidental type regressions, consider turning the if let blocks into matches (or adding an else { panic!(...) }) so a non‑EVM/Non‑Solana variant can’t silently skip the assertions.

Example tightening for the EVM assertion
-        let evm_network = config
-            .get_network(ConfigFileNetworkType::Evm, "testnet")
-            .unwrap();
-        if let NetworkFileConfig::Evm(evm_config) = evm_network {
-            assert_eq!(evm_config.chain_id, Some(11155111));
-            assert!(evm_config.common.rpc_urls.is_some());
-            assert_eq!(evm_config.common.rpc_urls.as_ref().unwrap().len(), 2);
-        }
+        let evm_network = config
+            .get_network(ConfigFileNetworkType::Evm, "testnet")
+            .unwrap();
+        match evm_network {
+            NetworkFileConfig::Evm(evm_config) => {
+                assert_eq!(evm_config.chain_id, Some(11155111));
+                assert!(evm_config.common.rpc_urls.is_some());
+                assert_eq!(evm_config.common.rpc_urls.as_ref().unwrap().len(), 2);
+            }
+            other => panic!("Expected Evm network config, got {:?}", other),
+        }
src/models/network/evm/network.rs (1)

6-7: EvmNetwork RpcConfig migration and tests look correct

  • rpc_urls: Vec<RpcConfig> plus public_rpc_urls(&[RpcConfig]) matches the new shared RPC model and the provider trait helpers.
  • Tests building networks and configs with RpcConfig::new(...) correctly exercise the updated types and inheritance behavior.

If you prefer, you could pull use crate::models::RpcConfig; up to the top of the tests module instead of scattering function‑local imports, but that’s purely stylistic.

Also applies to: 14-16, 160-166, 176-191, 284-315

src/domain/relayer/evm/evm_relayer.rs (1)

59-61: RPC error sanitization and logging look good

Forwarding only (code, message) from map_provider_error plus a sanitize_error_description-derived description while logging the full ProviderError via tracing::error! cleanly separates internal detail from the external JSON‑RPC response. This aligns well with the stated RPC‑sanitization goals, and the plumbing through create_error_response is correct.

Also applies to: 492-508

src/domain/relayer/evm/rpc_utils.rs (1)

12-15: Error‑mapping re‑export and integration tests are consistent

Re‑exporting map_provider_error / sanitize_error_description from rpc_utils while delegating to crate::utils is a clean way to avoid duplication and preserve older import paths. The integration tests that build ProviderError variants and assert the resulting JSON‑RPC error codes align with the shared implementation in src/utils/error_sanitization.rs, so the wiring looks correct.

Also applies to: 72-75, 403-483

src/domain/relayer/solana/solana_relayer.rs (1)

836-848: Make insufficient‑funds token‑swap trigger best‑effort

On SolanaRpcError::InsufficientFunds, check_balance_and_trigger_token_swap_if_needed().await? means any failure in scheduling the token‑swap job bubbles up as a RelayerError instead of returning the mapped JSON‑RPC INSUFFICIENT_FUNDS error.

Consider logging failures from check_balance_and_trigger_token_swap_if_needed and still returning the JSON‑RPC error so clients always see a consistent insufficiency error, regardless of background job health.

src/utils/error_sanitization.rs (1)

40-95: Centralized provider error mapping and sanitization look solid

The mapping and sanitization functions are consistent and well‑covered by tests; the wildcard handling of Solana/selector/transport errors to INTERNAL_ERROR is reasonable for now.

If you add more ProviderError variants later, it may be worth making map_provider_error exhaustive (no _ arm) so the compiler forces you to decide on explicit codes per variant.

src/api/routes/network.rs (1)

40-46: Align route‑registration comment with actual order

The comment says “Register routes with literal segments before routes with path parameters”, but init currently registers the parameterized handlers before list_networks. Behavior is fine, but either reorder the cfg.service calls or update the comment to avoid confusion for future readers.

src/config/config_file/network/common.rs (1)

17-56: RpcConfig deserialization and merge semantics look correct

The custom deserialize_rpc_urls, the switch to Option<Vec<RpcConfig>>, and merge_optional_rpc_config_vecs all align with the documented behavior (simple + extended formats, child‑overrides semantics), and the tests thoroughly exercise validation, serialization round‑trips, and parent/child merge behavior.

You now have essentially the same deserialize_rpc_urls logic in both this module and src/models/network/request.rs. If this evolves (e.g., more fields on RpcConfig), consider extracting a shared helper to keep behavior in sync.

Also applies to: 80-108, 186-195, 813-985

src/models/network/response.rs (1)

13-113: NetworkResponse mapping from NetworkRepoModel is consistent

The flattening of common fields plus EVM/Stellar‑specific additions in From<NetworkRepoModel> for NetworkResponse matches the underlying configs, and the EVM tests verify both type‑specific and common fields.

Consider adding small tests for Solana and Stellar models to catch regressions in those branches of the match as fields evolve.

Also applies to: 115-166

src/models/network/request.rs (1)

19-80: Flexible rpc_urls request model and validation look good

The untagged RpcUrlEntry for schema purposes, the custom deserialize_rpc_urls (strings, objects, and mixed), and UpdateNetworkRequest::validate together give a nicely flexible yet validated RPC URL update surface; the tests exercise the key shapes and error cases.

You might eventually want to (a) share the deserializer with the config/common module to avoid drift, and (b) lean on DEFAULT_RPC_WEIGHT (via RpcConfig or constants) in tests instead of hard‑coding 100u8, so a future default change doesn’t require updating multiple places.

Also applies to: 82-130, 132-248

src/services/provider/evm/mod.rs (1)

201-226: New provider initialization logging is fine; consider structured fields

initialize_provider now logs the URL being initialized. To align with structured tracing patterns elsewhere, you might prefer something like info!(%url, "initializing EVM provider"); instead of interpolating into the message string, but behavior is otherwise correct.

src/models/relayer/rpc_config.rs (1)

112-148: URL validation helpers and tests are solid; minor doc-type mismatch only.

The validate_url_scheme / validate_list helpers and their tests cover the expected HTTP/HTTPS vs. invalid-scheme cases well, and the switch to eyre::Report integrates with the rest of the error stack.

Minor nit: the # Returns doc comment on validate_list still says Result<()> while the signature is Result<(), eyre::Report>. Consider updating or omitting the concrete type in the docs to avoid confusion.

Also applies to: 205-287

src/services/provider/stellar/mod.rs (2)

274-331: Exposing RPC configs via get_configs is consistent; cloning is acceptable

Adding fn get_configs(&self) -> Vec<RpcConfig> to StellarProviderTrait and delegating to the inherent StellarProvider::get_configs cleanly surfaces the selector’s current config set. Returning an owned Vec<RpcConfig> is reasonable here given the small list size and avoids lifetime complexity.

If you ever need cheaper read-only access in hot paths, consider an additional method returning a slice (&[RpcConfig]) on the concrete provider and using that where cloning isn’t needed.

Also applies to: 373-380, 502-507


1005-1008: Test helpers for ProviderConfig are correct but duplicated

Both create_test_provider_config helpers build ProviderConfig::new(configs, timeout, 3, 60, 60) and the updated tests exercise the new constructor paths and error cases correctly.

To avoid test-only duplication, you could expose a single helper (e.g. top-level in this module) and reuse it in concrete_tests via super::create_test_provider_config.

Also applies to: 1294-1297, 1013-1097, 1081-1097

src/config/server_config.rs (2)

31-80: Provider health config fields and env wiring are consistent

The new provider_failure_threshold, provider_pause_duration_secs, and provider_failure_expiration_secs fields are correctly:

  • Documented in from_env defaults.
  • Populated via the new getters.
  • Exposed as plain public fields for downstream use in ProviderConfig::from_server_config.

The getters’ behavior (env → legacy env → DEFAULT_* with parse fallback) matches the pattern used elsewhere in this module.

Given these values drive RpcHealthStore behavior, you may want to document or clamp pathological cases (e.g., threshold=0 or pause/expiration=0) if those are not intended to be supported configurations.

Also applies to: 100-106, 124-132, 282-312


399-407: Consider extending tests to cover new provider health getters

The existing tests validate:

  • Default values for provider_failure_threshold and provider_pause_duration_secs.
  • from_env equivalence with individual getters (for pre-existing fields).

They don’t yet:

  • Assert the default for provider_failure_expiration_secs.
  • Exercise get_provider_failure_threshold, get_provider_pause_duration_secs, and get_provider_failure_expiration_secs directly or with custom/legacy env vars.

Adding a small set of assertions for these getters (including precedence of legacy RPC_* variables) would lock in the new behavior and guard future refactors.

Also applies to: 426-428, 555-608, 712-791

src/services/provider/mod.rs (1)

22-99: ProviderConfig and get_network_provider composition look correct

ProviderConfig cleanly encapsulates RPC configs, timeouts, and health parameters, and:

  • from_server_config/from_env correctly translate ServerConfig fields (including ms→s for timeouts and the new provider_* health fields).
  • get_network_provider selects custom vs public RPC configs as intended, errors when none are available, and then constructs a ProviderConfig via from_env for all networks before delegating to N::new_provider.

Once the public_rpc_urls recursion is fixed, this centralization should make adding future provider knobs straightforward.

If you ever need sub-second timeouts, consider switching ProviderConfig::timeout_seconds to a Duration or carrying both ms and s explicitly to avoid the integer division truncation in from_server_config.

Also applies to: 251-261, 327-346

src/services/provider/rpc_health_store.rs (1)

13-247: RpcHealthStore design and semantics look solid

The new health store:

  • Uses a global Lazy<RpcHealthStore> with Arc<RwLock<...>> for safe shared state.
  • Correctly prunes stale failures on both mark_failed and is_paused, caps history at threshold * 2, and updates paused_until with clear logging for first-pause vs extension.
  • Cleans up metadata entries when pauses expire and no recent failures remain, avoiding unbounded map growth.
  • Is thoroughly exercised by tests, including stale vs recent failure mixes, pause extension, and shared-instance behavior.

The only slightly unusual edge case is threshold == 0, which effectively means “pause on first failure” with zero retained timestamps; that’s consistent but worth documenting if users might accidentally configure it.

Also applies to: 249-705

src/services/provider/solana/mod.rs (1)

1025-1036: Test updates for ProviderConfig usage are consistent

The new create_test_provider_config helper and the refactored tests that construct SolanaProvider via:

SolanaProvider::new(create_test_provider_config(configs, timeout))

or

SolanaProvider::new_with_commitment_and_health(configs, timeout, commitment, 3, 60, 60)

are aligned with the new configuration model and correctly assert:

  • Success for valid configs (single/multiple URLs).
  • ProviderError::NetworkConfiguration for empty or invalid config lists.

This keeps Solana tests in sync with the EVM/Stellar provider patterns.

You could reuse create_test_provider_config in all local tests (including commitment-specific ones) to avoid hard-coding the health parameters in multiple places.

Also applies to: 1037-1111, 1140-1154

src/services/provider/rpc_selector.rs (3)

22-22: Import additional tracing macros used in the code.

The code uses tracing::warn! and tracing::debug! (e.g., line 337), but only info is imported. This requires fully-qualified paths elsewhere.

🔎 Suggested import fix
-use tracing::info;
+use tracing::{debug, info, warn};

167-167: Use more appropriate log level for failures.

Marking a provider as failed is a significant event that affects availability. Consider using warn! instead of info! to ensure it's visible in production logs at standard levels.

🔎 Proposed change
-        info!("Marking current provider as failed");
+        warn!("Marking current provider as failed");

426-429: Consider preserving error details in client initialization.

Line 428 converts the error using e.to_string(), which loses the underlying error type and source chain. For debugging, consider preserving the full error context.

💡 Alternative error handling
-        initializer(&url).map_err(|e| RpcSelectorError::ClientInitializationError(e.to_string()))
+        initializer(&url).map_err(|e| {
+            RpcSelectorError::ClientInitializationError(format!("{:#}", e))
+        })

Using {:#} preserves the error chain, providing more context for debugging.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between caa5803 and 8359191.

📒 Files selected for processing (69)
  • docs/configuration/index.mdx
  • openapi.json
  • src/api/controllers/mod.rs
  • src/api/controllers/network.rs
  • src/api/controllers/relayer.rs
  • src/api/routes/docs/mod.rs
  • src/api/routes/docs/network_docs.rs
  • src/api/routes/mod.rs
  • src/api/routes/network.rs
  • src/api/routes/relayer.rs
  • src/config/config_file/mod.rs
  • src/config/config_file/network/collection.rs
  • src/config/config_file/network/common.rs
  • src/config/config_file/network/evm.rs
  • src/config/config_file/network/inheritance.rs
  • src/config/config_file/network/mod.rs
  • src/config/config_file/network/test_utils.rs
  • src/config/server_config.rs
  • src/constants/relayer.rs
  • src/domain/relayer/evm/evm_relayer.rs
  • src/domain/relayer/evm/rpc_utils.rs
  • src/domain/relayer/solana/dex/jupiter_swap.rs
  • src/domain/relayer/solana/dex/jupiter_ultra.rs
  • src/domain/relayer/solana/rpc/methods/fee_estimate.rs
  • src/domain/relayer/solana/rpc/methods/prepare_transaction.rs
  • src/domain/relayer/solana/rpc/methods/sign_and_send_transaction.rs
  • src/domain/relayer/solana/rpc/methods/sign_transaction.rs
  • src/domain/relayer/solana/rpc/methods/transfer_transaction.rs
  • src/domain/relayer/solana/rpc/methods/utils.rs
  • src/domain/relayer/solana/solana_relayer.rs
  • src/domain/relayer/stellar/gas_abstraction.rs
  • src/domain/relayer/stellar/stellar_relayer.rs
  • src/domain/relayer/stellar/token_swap.rs
  • src/domain/transaction/evm/evm_transaction.rs
  • src/domain/transaction/evm/price_calculator.rs
  • src/domain/transaction/evm/status.rs
  • src/domain/transaction/evm/utils.rs
  • src/domain/transaction/stellar/test_helpers.rs
  • src/models/network/evm/network.rs
  • src/models/network/mod.rs
  • src/models/network/repository.rs
  • src/models/network/request.rs
  • src/models/network/response.rs
  • src/models/network/solana/network.rs
  • src/models/network/stellar/network.rs
  • src/models/relayer/mod.rs
  • src/models/relayer/rpc_config.rs
  • src/models/transaction/repository.rs
  • src/openapi.rs
  • src/repositories/network/network_in_memory.rs
  • src/repositories/network/network_redis.rs
  • src/repositories/relayer/mod.rs
  • src/services/gas/cache.rs
  • src/services/gas/evm_gas_price.rs
  • src/services/gas/fetchers/default.rs
  • src/services/gas/fetchers/mod.rs
  • src/services/gas/fetchers/polygon_zkevm.rs
  • src/services/gas/price_params_handler.rs
  • src/services/jupiter/mod.rs
  • src/services/provider/evm/mod.rs
  • src/services/provider/mod.rs
  • src/services/provider/retry.rs
  • src/services/provider/rpc_health_store.rs
  • src/services/provider/rpc_selector.rs
  • src/services/provider/solana/mod.rs
  • src/services/provider/stellar/mod.rs
  • src/utils/error_sanitization.rs
  • src/utils/mocks.rs
  • src/utils/mod.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (.cursor/rules/rust_standards.mdc)

**/*.rs: Follow official Rust style guidelines using rustfmt (edition = 2021, max_width = 100)
Follow Rust naming conventions: snake_case for functions/variables, PascalCase for types, SCREAMING_SNAKE_CASE for constants and statics
Order imports alphabetically and group by: std, external crates, local crates
Include relevant doc comments (///) on public functions, structs, and modules. Use comments for 'why', not 'what'. Avoid redundant doc comments
Document lifetime parameters when they're not obvious
Avoid unsafe code unless absolutely necessary; justify its use in comments
Write idiomatic Rust: Prefer Result over panic, use ? operator for error propagation
Avoid unwrap; handle errors explicitly with Result and custom Error types for all async operations
Prefer header imports over function-level imports of dependencies
Prefer borrowing over cloning when possible
Use &str instead of &String for function parameters
Use &[T] instead of &Vec for function parameters
Avoid unnecessary .clone() calls
Use Vec::with_capacity() when size is known in advance
Use explicit lifetimes only when necessary; infer where possible
Always use Tokio runtime for async code. Await futures eagerly; avoid blocking calls in async contexts
Streams: Use futures::StreamExt for processing streams efficiently
Always use serde for JSON serialization/deserialization with #[derive(Serialize, Deserialize)]
Use type aliases for complex types to improve readability
Implement common traits (Debug, Clone, PartialEq) where appropriate, using derive macros when possible
Implement Display for user-facing types
Prefer defining traits when implementing services to make mocking and testing easier
For tests, prefer existing utils for creating mocks instead of duplicating code
Use assert_eq! and assert! macros appropriately
Keep tests minimal, deterministic, and fast
Use tracing for structured logging, e.g., tracing::info! for request and error logs
When optimizing, prefer clarity first, then performance
M...

Files:

  • src/api/routes/docs/mod.rs
  • src/api/controllers/mod.rs
  • src/domain/transaction/evm/price_calculator.rs
  • src/constants/relayer.rs
  • src/domain/relayer/solana/rpc/methods/sign_transaction.rs
  • src/domain/transaction/evm/evm_transaction.rs
  • src/config/config_file/network/collection.rs
  • src/domain/relayer/solana/dex/jupiter_ultra.rs
  • src/utils/mod.rs
  • src/domain/relayer/solana/rpc/methods/prepare_transaction.rs
  • src/services/gas/fetchers/default.rs
  • src/models/relayer/mod.rs
  • src/api/controllers/network.rs
  • src/domain/transaction/stellar/test_helpers.rs
  • src/models/network/response.rs
  • src/models/network/mod.rs
  • src/services/gas/fetchers/polygon_zkevm.rs
  • src/domain/relayer/solana/rpc/methods/sign_and_send_transaction.rs
  • src/models/network/stellar/network.rs
  • src/utils/error_sanitization.rs
  • src/domain/relayer/stellar/stellar_relayer.rs
  • src/config/config_file/network/mod.rs
  • src/services/jupiter/mod.rs
  • src/api/routes/relayer.rs
  • src/openapi.rs
  • src/config/config_file/network/evm.rs
  • src/domain/relayer/solana/dex/jupiter_swap.rs
  • src/config/config_file/network/test_utils.rs
  • src/api/routes/network.rs
  • src/api/routes/docs/network_docs.rs
  • src/config/server_config.rs
  • src/services/gas/cache.rs
  • src/domain/relayer/evm/rpc_utils.rs
  • src/domain/relayer/solana/rpc/methods/utils.rs
  • src/services/provider/retry.rs
  • src/domain/relayer/solana/rpc/methods/transfer_transaction.rs
  • src/domain/transaction/evm/utils.rs
  • src/repositories/network/network_redis.rs
  • src/api/controllers/relayer.rs
  • src/services/provider/mod.rs
  • src/domain/relayer/solana/solana_relayer.rs
  • src/models/relayer/rpc_config.rs
  • src/models/network/request.rs
  • src/config/config_file/network/common.rs
  • src/domain/transaction/evm/status.rs
  • src/models/network/repository.rs
  • src/services/provider/solana/mod.rs
  • src/services/gas/evm_gas_price.rs
  • src/services/provider/rpc_health_store.rs
  • src/config/config_file/network/inheritance.rs
  • src/domain/relayer/solana/rpc/methods/fee_estimate.rs
  • src/repositories/relayer/mod.rs
  • src/domain/relayer/evm/evm_relayer.rs
  • src/config/config_file/mod.rs
  • src/models/network/evm/network.rs
  • src/services/gas/price_params_handler.rs
  • src/api/routes/mod.rs
  • src/services/provider/evm/mod.rs
  • src/services/provider/stellar/mod.rs
  • src/services/provider/rpc_selector.rs
  • src/models/transaction/repository.rs
  • src/domain/relayer/stellar/gas_abstraction.rs
  • src/services/gas/fetchers/mod.rs
  • src/repositories/network/network_in_memory.rs
  • src/domain/relayer/stellar/token_swap.rs
  • src/models/network/solana/network.rs
  • src/utils/mocks.rs
🧠 Learnings (8)
📚 Learning: 2025-08-19T14:31:09.686Z
Learnt from: LuisUrrutia
Repo: OpenZeppelin/openzeppelin-relayer PR: 427
File: src/models/network/evm/network.rs:1-1
Timestamp: 2025-08-19T14:31:09.686Z
Learning: In the OpenZeppelin relayer codebase, test helper functions may use network names (like "optimism") as string literals for creating mock networks, which are different from network tag constants (like OPTIMISM_BASED_TAG). These should not be flagged as inconsistencies when reviewing tag-related changes.

Applied to files:

  • src/config/config_file/network/collection.rs
  • src/config/config_file/network/test_utils.rs
  • src/services/gas/price_params_handler.rs
📚 Learning: 2025-08-19T10:41:31.051Z
Learnt from: LuisUrrutia
Repo: OpenZeppelin/openzeppelin-relayer PR: 428
File: config/networks/bsc.json:30-32
Timestamp: 2025-08-19T10:41:31.051Z
Learning: The network inheritance mechanism in OpenZeppelin Relayer configs correctly resolves `from` references within the appropriate scope, preventing false positive collisions between networks with similar names across different blockchain types.

Applied to files:

  • src/config/config_file/network/collection.rs
📚 Learning: 2025-12-02T11:22:31.387Z
Learnt from: CR
Repo: OpenZeppelin/openzeppelin-relayer PR: 0
File: .cursor/rules/rust_standards.mdc:0-0
Timestamp: 2025-12-02T11:22:31.387Z
Learning: Applies to **/*.rs : For tests, prefer existing utils for creating mocks instead of duplicating code

Applied to files:

  • src/utils/mod.rs
  • src/domain/transaction/stellar/test_helpers.rs
  • src/services/provider/retry.rs
  • src/repositories/relayer/mod.rs
  • src/domain/relayer/evm/evm_relayer.rs
  • src/utils/mocks.rs
📚 Learning: 2025-12-02T11:22:31.387Z
Learnt from: CR
Repo: OpenZeppelin/openzeppelin-relayer PR: 0
File: .cursor/rules/rust_standards.mdc:0-0
Timestamp: 2025-12-02T11:22:31.387Z
Learning: Applies to **/*.rs : Avoid unwrap; handle errors explicitly with Result and custom Error types for all async operations

Applied to files:

  • src/utils/mod.rs
  • src/utils/error_sanitization.rs
  • src/domain/relayer/evm/rpc_utils.rs
📚 Learning: 2025-12-02T11:22:31.387Z
Learnt from: CR
Repo: OpenZeppelin/openzeppelin-relayer PR: 0
File: .cursor/rules/rust_standards.mdc:0-0
Timestamp: 2025-12-02T11:22:31.387Z
Learning: Applies to **/*.rs : Prefer defining traits when implementing services to make mocking and testing easier

Applied to files:

  • src/domain/transaction/stellar/test_helpers.rs
  • src/services/provider/retry.rs
  • src/domain/relayer/solana/solana_relayer.rs
  • src/repositories/relayer/mod.rs
  • src/domain/relayer/evm/evm_relayer.rs
📚 Learning: 2025-12-02T11:22:31.387Z
Learnt from: CR
Repo: OpenZeppelin/openzeppelin-relayer PR: 0
File: .cursor/rules/rust_standards.mdc:0-0
Timestamp: 2025-12-02T11:22:31.387Z
Learning: Applies to **/*.rs : Keep tests minimal, deterministic, and fast

Applied to files:

  • src/services/provider/retry.rs
  • src/repositories/relayer/mod.rs
  • src/domain/relayer/evm/evm_relayer.rs
📚 Learning: 2025-12-02T11:22:31.387Z
Learnt from: CR
Repo: OpenZeppelin/openzeppelin-relayer PR: 0
File: .cursor/rules/rust_standards.mdc:0-0
Timestamp: 2025-12-02T11:22:31.387Z
Learning: Applies to **/*.rs : Use assert_eq! and assert! macros appropriately

Applied to files:

  • src/models/network/repository.rs
📚 Learning: 2025-12-02T11:22:31.387Z
Learnt from: CR
Repo: OpenZeppelin/openzeppelin-relayer PR: 0
File: .cursor/rules/rust_standards.mdc:0-0
Timestamp: 2025-12-02T11:22:31.387Z
Learning: Applies to **/*.rs : Use tracing for structured logging, e.g., tracing::info! for request and error logs

Applied to files:

  • src/services/provider/evm/mod.rs
🧬 Code graph analysis (29)
src/domain/transaction/evm/price_calculator.rs (1)
src/services/provider/mod.rs (1)
  • new (54-68)
src/config/config_file/network/collection.rs (4)
src/models/network/repository.rs (3)
  • config (136-138)
  • common (24-30)
  • common (131-133)
src/config/config_file/network/mod.rs (1)
  • is_testnet (100-106)
src/models/network/evm/network.rs (1)
  • is_testnet (135-137)
src/models/network/solana/network.rs (1)
  • is_testnet (83-85)
src/api/controllers/network.rs (5)
src/models/network/repository.rs (1)
  • config (136-138)
src/api/routes/network.rs (3)
  • list_networks (13-18)
  • get_network (22-27)
  • update_network (32-38)
src/config/config_file/network/collection.rs (1)
  • networks (138-142)
src/models/api_response.rs (2)
  • paginated (77-85)
  • success (47-55)
src/models/network/stellar/network.rs (1)
  • network_id (83-87)
src/models/network/response.rs (2)
src/models/network/repository.rs (2)
  • config (136-138)
  • new_evm (71-80)
src/models/network/evm/network.rs (1)
  • required_confirmations (140-142)
src/models/network/stellar/network.rs (3)
src/models/network/evm/network.rs (1)
  • public_rpc_urls (160-166)
src/models/network/solana/network.rs (1)
  • public_rpc_urls (71-77)
src/services/provider/mod.rs (4)
  • public_rpc_urls (254-254)
  • public_rpc_urls (266-270)
  • public_rpc_urls (280-284)
  • public_rpc_urls (294-298)
src/domain/relayer/stellar/stellar_relayer.rs (2)
src/utils/error_sanitization.rs (2)
  • map_provider_error (40-56)
  • sanitize_error_description (71-96)
src/domain/relayer/evm/rpc_utils.rs (1)
  • create_error_response (31-47)
src/config/config_file/network/mod.rs (1)
src/services/provider/mod.rs (1)
  • new (54-68)
src/openapi.rs (1)
src/api/routes/docs/network_docs.rs (3)
  • doc_list_networks (69-69)
  • doc_get_network (132-132)
  • doc_update_network (197-197)
src/api/routes/network.rs (2)
src/api/controllers/network.rs (3)
  • list_networks (33-61)
  • get_network (73-102)
  • update_network (116-201)
src/models/network/stellar/network.rs (1)
  • network_id (83-87)
src/config/server_config.rs (1)
src/models/network/repository.rs (1)
  • config (136-138)
src/domain/relayer/evm/rpc_utils.rs (1)
src/utils/error_sanitization.rs (2)
  • map_provider_error (40-56)
  • sanitize_error_description (71-96)
src/services/provider/retry.rs (1)
src/services/provider/rpc_selector.rs (3)
  • new (79-111)
  • new_with_defaults (123-130)
  • available_provider_count (144-152)
src/services/provider/mod.rs (4)
src/services/provider/evm/mod.rs (2)
  • new (163-191)
  • new (545-555)
src/services/provider/stellar/mod.rs (2)
  • new (335-371)
  • new (845-860)
src/config/server_config.rs (1)
  • from_env (106-132)
src/models/network/evm/network.rs (1)
  • public_rpc_urls (160-166)
src/domain/relayer/solana/solana_relayer.rs (1)
src/services/provider/mod.rs (1)
  • new (54-68)
src/models/relayer/rpc_config.rs (1)
src/config/config_file/network/common.rs (1)
  • deserialize (81-107)
src/models/network/request.rs (1)
src/models/relayer/rpc_config.rs (1)
  • validate_list (142-148)
src/config/config_file/network/common.rs (1)
src/models/relayer/rpc_config.rs (2)
  • deserialize (54-69)
  • with_weight (96-101)
src/models/network/repository.rs (1)
src/services/provider/mod.rs (1)
  • new (54-68)
src/services/provider/solana/mod.rs (2)
src/services/provider/rpc_selector.rs (1)
  • get_configs (158-160)
src/services/provider/mod.rs (1)
  • new (54-68)
src/repositories/relayer/mod.rs (1)
src/repositories/mod.rs (4)
  • create (59-59)
  • list_all (61-61)
  • update (66-66)
  • delete_by_id (67-67)
src/domain/relayer/evm/evm_relayer.rs (2)
src/domain/relayer/evm/rpc_utils.rs (2)
  • create_error_response (31-47)
  • create_success_response (60-70)
src/utils/error_sanitization.rs (2)
  • map_provider_error (40-56)
  • sanitize_error_description (71-96)
src/models/network/evm/network.rs (5)
src/models/network/solana/network.rs (1)
  • public_rpc_urls (71-77)
src/models/network/stellar/network.rs (1)
  • public_rpc_urls (93-99)
src/services/provider/mod.rs (5)
  • public_rpc_urls (254-254)
  • public_rpc_urls (266-270)
  • public_rpc_urls (280-284)
  • public_rpc_urls (294-298)
  • new (54-68)
src/models/relayer/rpc_config.rs (1)
  • new (78-83)
src/domain/transaction/evm/utils.rs (3)
  • None (298-298)
  • None (330-330)
  • None (362-362)
src/services/gas/price_params_handler.rs (1)
src/services/provider/mod.rs (1)
  • new (54-68)
src/api/routes/mod.rs (8)
src/api/routes/network.rs (1)
  • init (41-46)
src/api/routes/relayer.rs (1)
  • init (219-243)
src/api/routes/plugin.rs (1)
  • init (49-53)
src/api/routes/metrics.rs (1)
  • init (124-128)
src/api/routes/api_keys.rs (1)
  • init (44-50)
src/api/routes/notification.rs (1)
  • init (61-67)
src/api/routes/signer.rs (1)
  • init (58-64)
src/api/routes/health.rs (1)
  • init (29-31)
src/services/provider/evm/mod.rs (2)
src/services/provider/rpc_selector.rs (1)
  • get_configs (158-160)
src/services/provider/mod.rs (2)
  • new (54-68)
  • from_env (95-98)
src/services/provider/stellar/mod.rs (2)
src/services/provider/rpc_selector.rs (1)
  • get_configs (158-160)
src/services/provider/mod.rs (2)
  • new (54-68)
  • from_env (95-98)
src/services/provider/rpc_selector.rs (1)
src/services/provider/rpc_health_store.rs (2)
  • instance (38-40)
  • is_paused (188-238)
src/domain/relayer/stellar/token_swap.rs (1)
src/services/provider/mod.rs (1)
  • new (54-68)
src/models/network/solana/network.rs (3)
src/models/network/evm/network.rs (1)
  • public_rpc_urls (160-166)
src/models/network/stellar/network.rs (1)
  • public_rpc_urls (93-99)
src/services/provider/mod.rs (4)
  • public_rpc_urls (254-254)
  • public_rpc_urls (266-270)
  • public_rpc_urls (280-284)
  • public_rpc_urls (294-298)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: boostsecurity - boostsecurityio/semgrep-pro
  • GitHub Check: msrv
  • GitHub Check: Unit Tests
  • GitHub Check: clippy
  • GitHub Check: Properties Tests
  • GitHub Check: Redirect rules - openzeppelin-relayer
  • GitHub Check: Header rules - openzeppelin-relayer
  • GitHub Check: Pages changed - openzeppelin-relayer
  • GitHub Check: Analyze (rust)
  • GitHub Check: semgrep/ci

Comment thread openapi.json
Comment thread src/api/routes/docs/network_docs.rs Outdated
Comment thread src/config/config_file/network/inheritance.rs Outdated
Comment thread src/services/provider/mod.rs
Comment thread src/services/provider/retry.rs
Comment thread src/services/provider/rpc_selector.rs
Comment thread src/services/provider/rpc_selector.rs Outdated
Comment thread src/services/provider/rpc_selector.rs
Comment thread src/services/provider/rpc_selector.rs Fixed
Comment thread src/services/provider/rpc_selector.rs Fixed
Comment thread src/services/provider/rpc_selector.rs Fixed
Comment thread src/services/provider/rpc_selector.rs Fixed

@LuisUrrutia LuisUrrutia left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

}

#[test]
fn test_deserialize_with_inheritance_resolution() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this test was removed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LuisUrrutia
Main reason for removing/changing is because i have removed inheritance part for rpc urls.

I think we do not need inheritance from parent for rpc urls.

Example: sepolia inherits mainnet. rpc urls are different and they should not be inherited.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging PR now but we can address in a new one if something is needed.

Comment thread src/models/relayer/rpc_config.rs Outdated

@NicoMolinaOZ NicoMolinaOZ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just minor comments. Let me know if you need a testing round for this RPC logic, thanks!

Comment thread src/services/provider/rpc_health_store.rs Outdated
Comment thread src/services/provider/rpc_health_store.rs Outdated
Comment thread src/repositories/network/network_in_memory.rs Fixed
@zeljkoX

zeljkoX commented Jan 12, 2026

Copy link
Copy Markdown
Collaborator Author

LGTM, just minor comments. Let me know if you need a testing round for this RPC logic, thanks!

Never enough testing. Definitely if you find some time try to test it. Thanks.

@zeljkoX
zeljkoX merged commit 0ac8b4c into main Jan 12, 2026
26 checks passed
@zeljkoX
zeljkoX deleted the rpc-impr branch January 12, 2026 10:14
@github-actions github-actions Bot locked and limited conversation to collaborators Jan 12, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants